home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************************
- *
- * $Source: /unixb/home/unixlib/source/unixlib37/src/unix/c/RCS/getcwd,v $
- * $Date: 1996/10/30 21:59:01 $
- * $Revision: 1.3 $
- * $State: Rel $
- * $Author: unixlib $
- *
- * $Log: getcwd,v $
- * Revision 1.3 1996/10/30 21:59:01 unixlib
- * Massive changes made by Nick Burret and Peter Burwood.
- *
- * Revision 1.2 1996/05/06 09:01:35 unixlib
- * Updates to sources made by Nick Burrett, Peter Burwood and Simon Callan.
- * Saved for 3.7a release.
- *
- * Revision 1.1 1996/04/19 21:35:27 simon
- * Initial revision
- *
- * Completely re-written by Alun Jones, auj@aber.ac.uk, 23/2/94,
- * The original version corrupted the P.S.D. when run.
- *
- * OS_Args 7 and Prefix$Dir hacke by Simon Callan
- * thanks to Andy (torq@gnu.ai.mit.edu) for the OS calls.
- ***************************************************************************/
-
- static const char rcs_id[] = "$Id: getcwd,v 1.3 1996/10/30 21:59:01 unixlib Rel $";
-
- #include <errno.h>
- #include <string.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <sys/os.h>
- #include <sys/param.h>
- #include <sys/syslib.h>
- #include <sys/swis.h>
-
- char *
- getcwd (char *buffer, size_t size)
- {
- char ro_path[MAXPATHLEN];
- char var[30]; /* Added by Steffan Corley,
- is there a known limit on the length of this variable? */
- char *rp = ro_path + MAXPATHLEN - 1;
- char b[MAXPATHLEN];
- register char *s, *t;
- int r[10];
- _kernel_oserror *e;
- int handle;
-
- if (size == 0 && buffer)
- {
- errno = EINVAL;
- return 0;
- }
-
- /* Try to read CSD variable - added by Steffan Corley for !Virtual
- compatibility */
-
- r[0] = (int) "FileSwitch$CurrentFilingSystem";
- r[1] = (int) ro_path;
- r[2] = MAXPATHLEN - 1;
- r[3] = 0;
- r[4] = 0;
- os_swi (OS_ReadVarVal, r);
-
- if (r[2] > 0)
- {
- ro_path[r[2]] = '\0';
- strcpy (var, "FileSwitch$");
- strcat (var, ro_path);
- strcat (var, "$CSD");
- strcat (ro_path, ":");
-
- r[0] = (int) var;
- r[1] = (int) (ro_path + (handle = strlen (ro_path)));
- r[2] = MAXPATHLEN - 1 - handle;
- r[3] = 0;
- r[4] = 0;
- os_swi (OS_ReadVarVal, r);
-
- if (r[2] > 0)
- { /* Read CSD var worked, parse the path name */
- ro_path[r[2] + handle] = '\0';
- s = ro_path;
- t = buffer;
- *t++ = '/';
- size--;
- while (*s && *s != '$' && size-- > 0)
- *t++ = *s++;
-
- while (*s && size-- > 0)
- {
- if (*s != '.')
- *t++ = *s;
- else
- *t++ = '/';
- s++;
- }
- if (size == 0)
- {
- errno = ERANGE;
- return 0;
- }
- else
- {
- *t = '\0';
- return buffer;
- }
- }
- }
-
- /* Try OS_Args 7 (get cannonicalised name) */
-
- /* Open CSD for read only */
- if (!os_fopen (0x40, "@", &handle))
- {
- r[0] = 7;
- r[1] = handle;
- r[2] = (int) ro_path;
- r[5] = MAXPATHLEN;
- e = os_swi (OS_Args, r);
- os_fclose (handle);
- if (!e)
- { /* OS_ARGS 7 worked, parse the path name */
- s = ro_path;
- t = buffer;
- *t++ = '/';
- size--;
- while (*s && *s != '$' && size-- > 0)
- *t++ = *s++;
-
- while (*s && size-- > 0)
- {
- if (*s != '.')
- *t++ = *s;
- else
- *t++ = '/';
- s++;
- }
- if (size == 0)
- {
- errno = ERANGE;
- return 0;
- }
- else
- {
- *t = '\0';
- return buffer;
- }
- }
- }
-
- r[0] = (int) "Prefix$Dir";
- r[1] = (int) ro_path;
- r[2] = MAXPATHLEN - 1;
- r[3] = 0;
- r[4] = 0;
- os_swi (OS_ReadVarVal, r);
- if (r[2] > 0)
- {
- ro_path[r[2]] = '\0';
- s = ro_path;
- t = buffer;
- *t++ = '/';
- size--;
- while (*s && *s != '$' && size-- > 0)
- *t++ = *s++;
-
- while (*s && size-- > 0)
- {
- if (*s != '.')
- *t++ = *s;
- else
- *t++ = '/';
- s++;
- }
- if (size == 0)
- {
- errno = ERANGE;
- return 0;
- }
- else
- {
- *t = '\0';
- return buffer;
- }
- }
- /* Search backwards up the tree.
- */
- *rp = 0;
- while (1)
- {
- /* Read current directory name
- */
- r[0] = 6;
- r[2] = (int) b;
- if (e = os_swi (OS_GBPB, r))
- {
- /* Failed to read dirname
- * So swap CSD & PSD then chdir back to original
- * directory.
- */
- __seterr (e);
- if (*rp)
- {
- r[0] = 0;
- r[1] = (int) "\\";
- if (!os_swi (OS_FSControl, r))
- {
- /* cd \ successful, so now need to cd \.{rp}
- */
- *--rp = '.';
- *--rp = '\\';
- }
- r[0] = 0;
- r[1] = (int) rp;
- os_swi (OS_FSControl, r);
- }
- return 0;
- }
-
- /* If at root directory then break
- */
- if ((b[2] == '$') && (b[1] == 1))
- {
- break;
- }
-
- /* Copy the directory name into the RISC OS name
- * buffer.
- */
- rp -= b[1];
- memcpy (rp, b + 2, b[1]);
- *--rp = '.';
-
- /* Now select PSD.
- */
- r[0] = 0;
- r[1] = (int) "\\";
- if (os_swi (OS_FSControl, r))
- {
- /* If cd \ failed then just cd ^
- */
- r[0] = 0;
- r[1] = (int) "^";
- os_swi (OS_FSControl, r);
- }
- else
- {
- /* Select new PSD.^
- * This ensures that the PSD doesn't get corrupted by
- * calling getcwd()
- */
- r[0] = 0;
- r[1] = (int) "\\.^";
- os_swi (OS_FSControl, r);
- }
- }
-
- /* OK, reached the root directory.
- */
- *--rp = '$';
-
- /* Again, PSD then original directory
- */
- r[0] = 0;
- r[1] = (int) "\\";
- if (e = os_swi (OS_FSControl, r))
- {
- __seterr (e);
- return 0;
- }
-
- r[0] = 0;
- r[1] = (int) rp;
- if (e = os_swi (OS_FSControl, r))
- {
- __seterr (e);
- return 0;
- }
-
- /* OK, rp now contains the current directory, and
- * the PSD is unchanged.
- *
- * Next find the FS name.
- */
-
- /* FS number
- */
- if (e = os_args (0, 0, 0, r))
- {
- __seterr (e);
- return 0;
- }
-
- /* Convert number to name
- */
- r[1] = r[0];
- r[2] = (int) b + 1;
- r[3] = MAXPATHLEN;
- r[0] = 33;
- if (e = os_swi (OS_FSControl, r))
- {
- __seterr (e);
- return (0);
- }
-
- /* Now have "/ADFS::", for example in b.
- */
- b[0] = '/';
- strcat (b, "::");
-
- /* Copy the disk name across to v
- */
- if (strlen (b) < size)
- {
- strcpy (buffer, b);
- }
- else
- {
- errno = ERANGE;
- return 0;
- }
-
- /* Next find the disk name
- */
- r[0] = 5;
- r[2] = (int) b;
- if (e = os_swi (OS_GBPB, r))
- {
- __seterr (e);
- return 0;
- }
- *(b + b[0] + 1) = '\0';
- strcat (b, ".$");
- if (strlen (buffer) + strlen (b + 1) < size)
- {
- strcat (buffer, b + 1);
- }
- else
- {
- errno = ERANGE;
- return 0;
- }
-
- /* buffer now contains "/ADFS::fred.$", for example.
-
- * Finally convert the RISC OS name from rp, appending it to v.
- */
- s = buffer + strlen (buffer);
- for (t = rp + 1; *t; t++)
- {
- if (s - buffer == size)
- {
- errno = ERANGE;
- return 0;
- }
- *s++ = (*t == '.') ? '/' : *t;
- }
- *s = '\0';
- return buffer;
- }
-
- /* BSD version of getcwd. */
-
- char *
- getwd (char *buffer)
- {
- return getcwd (buffer, 256);
- }
-